package happy.study.clique.module.study.demo1;

import happy.study.clique.module.study.demo1.code.LimitValidator;
import lombok.Builder;
import lombok.Data;

/**
 * @author fsq
 * @date 2021/11/3 16:41
 **/
public class RunMain {

    /**
     * 1、多个开关配置简化流程思路
     * 2、对于一些有多种开关配置的业务，一个开关往往需要存储两个字段，如：
     * boolean enableDay; // 是否开启每日限制
     * int dayNum; // 每日限制次数
     * 3、当配置项开始增加时，每次都要在数据库表拓展两个字段，且实现业务逻辑判断会很繁琐，因此有一个新的思路整合这些判断。
     * 4、 按位与的运算规则是将两边的数转换为二进制位，然后运算最终值，运算规则即(两个为真才为真)1&1=1
     * 5、例：7 & 1 = 1 ，按位与运算： 1001 & 0001 = 0001 当 mask码 7 与标识码 1 按位与的结果仍等于后者时，则可以标识为真，开关已打开
     * 6、我们用二进制中每一位代表一个开关，理论上可以支持到30种，java int 基本类型最大为：2<sup>31</sup>-1.
     */
    public static void main(String[] args) {

        //  mask = 7  (1 + 2 + 4),即等价: 年月周-限制开，日限制关。
        DbTable data = DbTable.builder().mask(7).build();
        final int mask = data.getMask();
        System.out.println("标识码：" + mask);
        System.out.println("是否开启年限制：" + LimitValidator.hasLimitYear(mask));
        System.out.println("是否开启月限制：" + LimitValidator.hasLimitMonth(mask));
        System.out.println("是否开启周限制：" + LimitValidator.hasLimitWeek(mask));
        System.out.println("是否开启日限制：" + LimitValidator.hasLimitDay(mask));

        // 月 + 周 限制开启，年日关闭
        final int mask1 = 2 + 8;
        System.out.println("标识码：" + mask1);
        System.out.println("是否开启年限制：" + LimitValidator.hasLimitYear(mask1));
        System.out.println("是否开启月限制：" + LimitValidator.hasLimitMonth(mask1));
        System.out.println("是否开启周限制：" + LimitValidator.hasLimitWeek(mask1));
        System.out.println("是否开启日限制：" + LimitValidator.hasLimitDay(mask1));
    }
}

/**
 * 模拟数据库字段
 */
@Builder
@Data
class DbTable {
    /**
     * 限制mode
     */
    private Integer mask;

    /**
     * 年限制次数
     */
    private Integer year;

    /**
     * 月限制次数
     */
    private Integer month;

    /**
     * 周限制次数
     */
    private Integer week;

    /**
     * 日限制次数
     */
    private Integer day;
}

/**
 * 旧的DB存储方式，需要存多个字段
 */
@Data
class DbOldTable {


    private Boolean enableYear;
    private Boolean enableMonth;
    private Boolean enableWeek;
    private Boolean enableDay;

    private Integer year;
    private Integer month;
    private Integer week;
    private Integer day;
}

/**
 * 当数据库需要频繁拓展字段的时候，不妨试一下以下结构
 */
@Data
class DbAdvanceTable {

    /**
     * 限制mode
     */
    private Integer mask;

    /**
     * json字符串合并存储字段 {"year"2:,"month"1:,"week":2,"day":5}
     */
    private String jsonData;
}